package com.yang.stream;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;

/**
 * 模拟API中的流式输出和非流式输出
 */
public class ApiStreamingExample {

    public static void main(String[] args) {
        System.out.println("API响应示例：");
        
        // 模拟流式API调用
        System.out.println("\n===== 流式API响应 =====");
        streamingApiCall(response -> {
            System.out.println("收到流式数据: " + response);
        });
        
        // 模拟非流式API调用
        System.out.println("\n===== 非流式API响应 =====");
        try {
            String response = nonStreamingApiCall().get();
            System.out.println("收到完整响应: \n" + response);
        } catch (InterruptedException | ExecutionException e) {
            System.err.println("API调用失败: " + e.getMessage());
        }
    }
    
    /**
     * 模拟流式API调用
     * 特点：数据一旦生成就立即通过回调发送给客户端
     * 应用场景：聊天机器人实时响应、大型文件下载进度、实时日志流等
     */
    public static void streamingApiCall(Consumer<String> responseHandler) {
        System.out.println("发起流式API请求...");
        
        // 模拟服务器处理和生成数据流的过程
        new Thread(() -> {
            try {
                // 模拟AI生成文本的过程
                String[] sentences = {
                    "您好，我是AI助手。",
                    "我正在使用流式输出方式回答您的问题。",
                    "流式输出可以让您看到我思考的过程。",
                    "不需要等待整个回答生成完毕就能看到部分内容。",
                    "这提供了更好的用户体验和交互感。"
                };
                
                for (String sentence : sentences) {
                    // 模拟服务器处理延迟
                    Thread.sleep(1000);
                    
                    // 立即将生成的部分发送给客户端
                    responseHandler.accept(sentence);
                }
                
                System.out.println("流式响应完成");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.err.println("流式处理中断: " + e.getMessage());
            }
        }).start();
    }
    
    /**
     * 模拟非流式API调用
     * 特点：所有数据全部生成完毕后才一次性返回给客户端
     * 应用场景：传统REST API、需要完整数据后才能处理的场景
     */
    public static CompletableFuture<String> nonStreamingApiCall() {
        System.out.println("发起非流式API请求...");
        
        return CompletableFuture.supplyAsync(() -> {
            try {
                StringBuilder fullResponse = new StringBuilder();
                
                // 模拟AI生成文本的过程
                String[] sentences = {
                    "您好，我是AI助手。",
                    "我正在使用非流式输出方式回答您的问题。",
                    "非流式输出会等待整个回答生成完毕。",
                    "您需要等待所有内容准备好后才能看到回答。",
                    "这在某些需要完整数据的场景中很有用。"
                };
                
                System.out.println("服务器正在生成完整响应...");
                
                for (String sentence : sentences) {
                    // 模拟服务器处理延迟
                    Thread.sleep(1000);
                    System.out.println("服务器内部: 已生成部分内容，但尚未发送");
                    
                    // 将内容添加到完整响应中，但不发送
                    fullResponse.append(sentence).append("\n");
                }
                
                System.out.println("服务器内部: 响应生成完毕，准备一次性发送");
                
                // 全部生成完成后，返回完整响应
                return fullResponse.toString();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("生成响应时出错", e);
            }
        });
    }
    
    /**
     * 示例：应用在实际业务场景中的流式响应
     */
    public static void realWorldExample() {
        // 模拟查询大型数据库并流式返回结果
        searchDatabase("用户查询", results -> {
            // 前端可以在接收到每个结果时就开始渲染，无需等待所有结果
            results.forEach(result -> {
                System.out.println("前端收到一条结果并展示: " + result);
            });
        });
    }
    
    /**
     * 模拟数据库查询并流式返回结果
     */
    private static void searchDatabase(String query, Consumer<List<String>> batchResultHandler) {
        new Thread(() -> {
            try {
                // 模拟多个数据库分片查询过程
                for (int i = 0; i < 5; i++) {
                    // 模拟从一个数据库分片查询结果
                    Thread.sleep(1000);
                    
                    // 每个批次找到的结果
                    List<String> batchResults = new ArrayList<>();
                    for (int j = 1; j <= 3; j++) {
                        batchResults.add("查询结果 #" + (i * 3 + j) + " 对应查询: " + query);
                    }
                    
                    // 每批次结果立即发送给前端，不等待所有批次完成
                    batchResultHandler.accept(batchResults);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();
    }
} 